﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Socket.Core;
using System.Net;
using System.IO;
using UnityEngine;
using MsgPack;

namespace NetWork
{
    public class NetManager
    {
        private static NetManager _Instance = new NetManager();
        public List<ReceiveMsgInfo> ReceiveMsgs = new List<ReceiveMsgInfo>();
        public static readonly object MsgLocker = new object();

        public IClient Client { get; set; }
        public ClientConfig Config { get; set; }
        public NetStateEnum NetState { get; set; }

        public NetManager()
        {
            this.NetState = NetStateEnum.NSE_DISCONNECTED;
            string ipString = "127.0.0.1";
            int port = 0x2710;
            ClientConfig config = new ClientConfig(new IPEndPoint(IPAddress.Parse(ipString), port), 0x400)
            {
                RetryInterval = 0,
                RetryCount = 0,
                MaxConnection = 1,
                Blocking = false,
                ReceiveTimeout = 0x1312d00,
                SendTimeout = 0x1312d00,
                MaxMessageLength = 0xfa000
            };
            
            this.Config = config;
            this.Client = new SocketClient(new ServerCommand());
            this.Client.Received += new EventHandler<ReceivedArgs>(this.MsgThreadReceivedFunc);
            this.Client.Connected += new EventHandler<SessionArgs>(this.MsgThreadConnectedFunc);
            this.Client.DisConnected += new EventHandler<SessionArgs>(this.MsgThreadDisConnectedFunc);
            this.Client.HeartbeatReceived += new EventHandler<HeartbeatReceivedArgs>(this.MsgThreadHeartbeatReceivedFunc);
        }

        public void Connect(string Ip, int Port)
        {
            this.DisConnect();
            if (this.NetState < NetStateEnum.NSE_CONNECTED)
            {
                //Debug.Log(string.Format("Start connect server. ip:{0}  port:{1}", Ip, Port));
                this.Config.EndPoint = new IPEndPoint(IPAddress.Parse(Ip), Port);
                this.Client.Setup(this.Config);
                this.Client.StartConnect();
            }
        }

        protected virtual void MsgThreadReceivedFunc(object sender, ReceivedArgs receivedArgs)
        {
			//Debug.Log(string.Format("Received  Msg SessionId={0}", receivedArgs.Session.SessionId));
            ReceiveMsgInfo item = new ReceiveMsgInfo
            {
                ProtocolCode = receivedArgs.ReceiveInfo.MethodCode,
                MsgBody = ((MemoryStream)receivedArgs.ReceiveInfo.ReceiveStream).ToArray()
            };
            //Debug.Log(string.Format("Received Server Msg.MsgId={0}", item.ProtocolCode));

            object msgLocker = MsgLocker;
            lock (msgLocker)
            {
                this.ReceiveMsgs.Add(item);
				//Debug.Log(string.Format("消息分发： 111 {0}", item.ProtocolCode));
				//Debug.Log(string.Format("消息分发： {0}", item.ProtocolCode));
				//Debug.Log(string.Format("消息分发： end {0}", item.ProtocolCode));
				MessageMap.OnMessage((int)item.ProtocolCode,item.MsgBody);
				
				//Debug.Log(string.Format("消息分发： end {0}", item.ProtocolCode));
            }
        }
		
		
        protected virtual void MsgThreadConnectedFunc(object sender, SessionArgs e)
        {
            this.NetState = NetStateEnum.NSE_CONNECTED;
           // Debug.Log("MsgThreadConnectedFunc..");

			//e.Session.
			//Debug.Log(string.Format(" SessionId={0}",e.Session.SessionId));
			

			ObjectPacker packer = new ObjectPacker();
			Connected msg = new Connected();
			byte[] msgBuffer = packer.Pack(msg);
			Debug.Log("MsgThreadConnectedFunc=="+Connected.ID());
			MessageMap.OnMessage(Connected.ID(),msgBuffer);


        }

        protected virtual void MsgThreadDisConnectedFunc(object sender, SessionArgs e)
        {
            this.NetState = NetStateEnum.NSE_DISCONNECTED;
            //Debug.Log("MsgThreadDisConnectedFunc..");
			//Debug.Log(string.Format(" SessionId={0}",e.Session.SessionId));
			ObjectPacker packer = new ObjectPacker();
			Disconnected msg = new Disconnected();
			byte[] msgBuffer = packer.Pack(msg);
			Debug.Log("MsgThreadDisConnectedFunc=="+Connected.ID());
			MessageMap.OnMessage(Disconnected.ID(),msgBuffer);
	
        }

        protected virtual void MsgThreadHeartbeatReceivedFunc(object sender, HeartbeatReceivedArgs e)
        {
            Debug.Log("MsgThreadHeartbeatReceivedFunc..");
        }

        ~NetManager()
        {
            Debug.Log("Servers OnDestroy!");
            this.OnDestroy();
        }

        public void OnDestroy()
        {
            this.DisConnect();
        }

        public void DisConnect()
        {
            if (this.NetState >= NetStateEnum.NSE_CONNECTED)
            {
                this.NetState = NetStateEnum.NSE_DISCONNECTED;
                this.Client.DisConnect();
            }
        }
		public bool SendMessage(int msgID, System.Object msg, ushort iRouteId=0)
		{
			//GlobalMgr.instance.TimeOut ();
			ObjectPacker packer = new ObjectPacker();
			byte[] msgBuffer = packer.Pack(msg);
			if(Packet.IsNeedRoot((short)msgID))
			{

				//iRouteId=LobbySysterm.GetInstance().GetRouteID();
				//Debug.Log(string.Format("iRouteId={0},msgid={1}",iRouteId,msgID));
				//return this.Client.ServerSession.Send(new ServerMessage(msgID, msgBuffer, 2));
			}
			//Debug.Log("Servers OnDestroy!" + msgBuffer.Length);
			return this.Client.ServerSession.Send(new ServerMessage(msgID, msgBuffer, iRouteId));
			
			
		}
       // public bool SendNetMessage<T>(int msgID, T tData)
        //{
         //   ObjectPacker packer = new ObjectPacker();
         //   byte[] msgBuffer = packer.Pack(tData);
         //   return this.Client.ServerSession.Send(new GateMessage(msgID, msgBuffer));
            
       // }

       // public bool SendNetMessage<T>(int msgID, T tData, ushort iRouteId)
       // {
        //    ObjectPacker packer = new ObjectPacker();
        //    byte[] msgBuffer = packer.Pack(tData);
         //   return this.Client.ServerSession.Send(new ServerMessage(msgID, msgBuffer, iRouteId));
        //}

        public T UnPackMsg<T>(byte[] buff)
        {
            ObjectPacker packer = new ObjectPacker();
            return (T)packer.Unpack(typeof(T), buff);
        }

        public static NetManager Instance
        {
            get
            {
                return _Instance;
            }
        }
    }
}
